﻿

namespace Tentacle.Core
{
    //
    using System;
    using System.Collections.Generic;
    using System.IO;

    //
    using Tentacle.Scheduler;
    using Tentacle.Processor;
    using Tentacle.Pipeline;

    public class TentacleCore
    {
        IScheduler          _scheduler;
        IWebPipeline        _pipeline;
        IPageProcessor[]    _processor;

        public TentacleCore(IPageProcessor[] processor, IWebPipeline pipeline,int delay)
        {
            _pipeline = pipeline ?? throw new NullReferenceException();
            _processor = processor ?? throw new NullReferenceException();

            _scheduler = new MemoryScheduler() { PeroidTime = delay};
            if (processor.Length == 1) {
                _scheduler.SetPageProcessor(processor[0]);
            }
            else if (processor.Length > 1) {
                _scheduler.SetPageProcessor(processor);
            }
            else {
                throw new ArgumentException("页面处理器不可为空");
            }

            _scheduler.SetPipeline(_pipeline);
        }

        #region Property

        /// <summary>
        /// 获取或设置一个值，该值指示是否将下载完成的原始页面缓存
        /// </summary>
        public bool IsCacheRawHtml { get; set; }

        /// <summary>
        /// 获取或设置缓存目录，只有当IsCacheRawHtml为true时该属性才会生效
        /// </summary>
        public string CacheFolder { get; set; }

        /// <summary>
        /// 
        /// </summary>
        public int UnFinishedCount {
            get {
                return _scheduler.TaskQueue.Count;
            }
        }

        public int FinishedCount {
            get {
                return _scheduler.FinishedCount;
            }
        }

        #endregion

        #region Public Method

        public void SaveProgress(string folder)
        {
            List<string> website = new List<string>();

            // copy
            lock (_scheduler.TaskQueue) {
                foreach (var site in _scheduler.TaskQueue) {
                    website.Add(site.Url);
                }
            }

            List<string> nameTable = new List<string>();
            lock (_scheduler.FinishedPool) {
                foreach (var name in _scheduler.FinishedPool) {
                    nameTable.Add(name.Url);
                }
            }

            File.WriteAllLines(folder + "site.txt", website);
            File.WriteAllLines(folder + "nametable.txt", nameTable);
        }

        public void LoadProgress(string folder)
        {
            var sites = File.ReadAllLines(folder + "site.txt");
            var names = File.ReadAllLines(folder + "nametable.txt");
            _scheduler.RebuildProgress(sites, names);
        }

        public void Start(string entry)
        {
            _scheduler.DownloadCompleted = OnDownloadCompleted;
            _scheduler.DownloadFailed = OnDownloadFailed;

            _scheduler.Start(new WebSite(entry));
        }
        #endregion

        void OnDownloadCompleted(WebPage page)
        {
            if (IsCacheRawHtml && !string.IsNullOrEmpty(CacheFolder)) {
                File.WriteAllText(Path.Combine(CacheFolder, page.Hash + ".html"), page.Html);
            }
            DownloadCompleted?.Invoke(page.Site.Url);
        }

        public event Action<string> DownloadCompleted;
        public event Action<string> DownloadFailed;

        void OnDownloadFailed(string error)
        {            
            DownloadFailed?.Invoke(error);
        }
    }
}
